package com.zhiwang.planet.service

import android.app.DownloadManager
import android.app.Service
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.IntentFilter
import android.database.ContentObserver
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.os.Handler
import android.os.IBinder
import androidx.core.content.FileProvider
import com.zhiwang.planet.BuildConfig
import com.zhiwang.planet.event.AppDownLoadProgressEvent
import com.zhiwang.planet.util.Utils
import org.greenrobot.eventbus.EventBus
import java.io.File


class GameApkDownLoadService : Service() {
    companion object InnerDB {

        val URL_KEY = "URL"

        val APPNAME_KEY = "MD5"

        private var dm: DownloadManager? = null

        private var downloadId: Long = 0


        fun start(context: Context, url: String, appPackageName: String) {
            val service = Intent(context, GameApkDownLoadService::class.java)
            service.putExtra(URL_KEY, url)
            service.putExtra(APPNAME_KEY, appPackageName)
            context.startService(service)
        }

        fun stopDownload() {
//            dm!!.remove(downloadId)
        }

        var downloadFileMap = hashMapOf<Long, File>()
        var downloadAppNameMap = hashMapOf<Long, String>()
        var downUriAppNameMap = hashMapOf<String, String>()
        var progressMap = hashMapOf<String, String>()

        fun getAppDownloadProgress(name: String): String {
            return if (progressMap.containsKey(name))
                progressMap[name]!!
            else ""
        }
    }


    //"content://downloads/my_downloads"必须这样写不可更改
    val CONTENT_URI = Uri.parse("content://downloads/my_downloads")
    private var downloadObserver: DownloadChangeObserver? = null


    private var receiver: BroadcastReceiver? = null

    var file = File(Environment.getExternalStorageDirectory().toString() + "/download/ji7app.apk")


    override fun onBind(intent: Intent): IBinder? {
        return null
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        if (receiver == null) {
            receiver = object : BroadcastReceiver() {
                override fun onReceive(context: Context, intent: Intent) {
                    var intent = intent
                    val longExtra = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1)
                    if (downloadFileMap.containsKey(longExtra)) {
                        val file = downloadFileMap[longExtra]!!
                        intent = Intent(Intent.ACTION_VIEW)
                        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
                        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
                            intent.setDataAndType(Uri.fromFile(file.absoluteFile),
                                    "application/vnd.android.package-archive")
                        else {

                            //部分手机 huawei nova 3i 上下载到外置存储的安装包都无法安装，所以拷贝一份到 app 私有目录
                            val newPath = File(filesDir.path + "/planetdownload")
                            if (!newPath.exists()) {
                                //通过file的mkdirs()方法创建 目录中包含却不存在的文件夹
                                newPath.mkdirs()
                            }
                            val path = newPath.path + File.separator + file.name
                            val oldPath = file.path
                            com.zhiwang.planet.util.Utils.copyFile(oldPath, path)
                            val newfile = File(path)
                            // 即在清单文件中配置的authorities
                            val uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, newfile)
                            // 给目标应用一个临时授权
                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)

//                            intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
                            intent.setDataAndType(uri/*FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, file)*/,
                                    "application/vnd.android.package-archive")
                        }

                        startActivity(intent)
                        downloadFileMap.remove(longExtra)
                        downloadAppNameMap.remove(longExtra)
                        //清空，释放资源
                        if (downloadFileMap.isEmpty())
                            stopSelf()
                    }

                }
            }
            registerReceiver(receiver, IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE))
        }

        //在进程被杀死后，重启 service 时intent为null
        if (intent != null) {
            val url = intent.getStringExtra(URL_KEY)
            val appName = intent.getStringExtra(APPNAME_KEY)
            progressMap[appName] = "0"
            startDownload(url, appName)
        }

        return START_STICKY
    }

    override fun onDestroy() {
        if (receiver != null)
            unregisterReceiver(receiver)
        //清除所有下载任务
        downloadAppNameMap.clear()
        downloadFileMap.clear()
        downUriAppNameMap.clear()
        progressMap.clear()
        if (downloadObserver != null)
            contentResolver.unregisterContentObserver(downloadObserver!!)
        super.onDestroy()
    }

    private fun startDownload(url: String, appName: String) {
//        nameFromUrl(url)
        val fileName = appName.plus(".apk")  //xxx.apk

        val file = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), fileName)
        if (file.exists()) {
            file.delete()
        }
        dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager
        val uri = Uri.parse(url)
        val request = DownloadManager.Request(
                uri)
        request.setMimeType("application/vnd.android.package-archive")
        request.setVisibleInDownloadsUi(true)
        request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName)
        val downloadId = dm!!.enqueue(request)
        downloadAppNameMap[downloadId] = appName
        downloadFileMap[downloadId] = file
        downloadObserver = DownloadChangeObserver(null)
        contentResolver.registerContentObserver(CONTENT_URI, true, downloadObserver)
    }

    private fun nameFromUrl(url: String): String {
        var fileName: String
        if (url.endsWith(".apk"))
            fileName = url.substring(url.lastIndexOf('/'), url.lastIndexOf('.'))
        else fileName = url.substring(url.lastIndexOf('/'))
        if (fileName.length > 20)
            fileName = fileName.substring(0, 11)
        return fileName.plus(".apk")
    }

    val TAG = "GameApkDownLoadService"

    //用于显示下载进度
    private inner class DownloadChangeObserver(handler: Handler?) : ContentObserver(handler) {

        override fun onChange(selfChange: Boolean) {
            val query = DownloadManager.Query()
            query.setFilterById(*downloadFileMap.keys.toLongArray())
            val dManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
            val cursor = dManager.query(query)
            if (cursor != null && cursor.moveToFirst()) {
                val totalColumn = cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES)
                val currentColumn = cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR)
                val idColumnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_ID)
                val totalSize = cursor.getInt(totalColumn)
                val currentSize = cursor.getInt(currentColumn)
                val id = cursor.getLong(idColumnIndex)
                val percent = currentSize.toFloat() / totalSize.toFloat()
                val progress = Math.round(percent * 100)

                if (downloadAppNameMap.containsKey(id)) {
                    val name = downloadAppNameMap[id]!!
                    progressMap[name] = progress.toString()
                }

//                Log.i(TAG, "onChange: id:$id    ${downloadAppNameMap.containsKey(id)}   progress:$progress ")
                EventBus.getDefault().post(AppDownLoadProgressEvent(progress = progress.toString(), name = downloadAppNameMap[id]
                        ?: ""))
                cursor.close()
            }
        }

    }
}